package org.finesys.common.log.trace.handler;

import org.finesys.common.log.annotation.LogMarker;
import org.finesys.common.log.trace.interceptor.AbstractInterceptor;
import org.finesys.common.log.trace.proxy.AroundLogProxyChain;
import org.finesys.common.log.trace.reflect.ReflectHandler;
import org.finesys.common.log.trace.tracer.Tracer;
import org.finesys.common.log.trace.util.LogstashUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;

public class AroundLogHandler extends AbstractInterceptor {

    public Object around(final AroundLogProxyChain chain) throws Throwable {
        Logger logger = getRealLogger(chain);
        mdcLogMarkerParam(chain);
        Tracer.trace(getTraceId(), getSpanId(), getParentId());
        logger.info(LogstashUtil.processBeginMarker(ReflectHandler.getInstance().getRequestParameter(chain)), LogstashUtil.kTYPE_BEGIN);
        long start = System.currentTimeMillis();
        Object o = null;
        try {
            o = chain.getProceed();
        } finally {
            logger.info(LogstashUtil.processSuccessDoneMarker(o != null ? ReflectHandler.getInstance().getResponseParameter(o) : null, System.currentTimeMillis() - start), LogstashUtil.kTYPE_DONE);
            Tracer.remove();
        }
        return o;
    }


    /**
     * 处理LogMaker注解中的参数
     *
     * @param chain chain
     */
    private void mdcLogMarkerParam(AroundLogProxyChain chain) {
        Method method = chain.getMethod();
        if (method.getAnnotation(LogMarker.class) != null) {
            LogMarker logMarker = method.getAnnotation(LogMarker.class);
            if (StringUtils.hasText(logMarker.interfaceName())) {
                MDC.put(LogstashUtil.kLOG_KEY_INTERFACE_NAME, logMarker.interfaceName());
            }
            if (StringUtils.hasText(logMarker.businessDescription())) {
                MDC.put(LogstashUtil.kLOG_KEY_REQUEST_TYPE, logMarker.businessDescription());
            }
        }
    }

    /**
     * 获取实际业务逻辑实现类的logger对象
     *
     * @param chain 切点
     * @return 返回能够真正打印日志位置的包名Logger
     */
    private Logger getRealLogger(AroundLogProxyChain chain) {
        return LoggerFactory.getLogger(chain.getClazz().getCanonicalName());
    }
}
